﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows;
using nl.tno.ict.multitouch.wpfmultitouch.controls;
using TouchLibEvents;
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows.Media.Media3D;


namespace nl.tno.ict.multitouch.wpfmultitouch
{

    
    public class Touch
    {
        public TouchManager TouchManager;
        public TouchedElement Selected;
        public TouchedElementStack Stack;
        public FingerObject Finger;

        private Visual GetFirstTouchObject(List<DependencyObject> ht)
        {
            foreach (DependencyObject obj in ht)
            {
                if ((bool)obj.GetValue(MTProperties.TouchEnabledProperty) && ((UIElement)obj).IsEnabled && (((UIElement)obj).Visibility == Visibility.Visible))
                {
                    return (Visual)obj;
                }
                else if (obj is Thumb || obj is RepeatButton || obj is ListBoxItem || obj is ToggleButton)
                {//Niet enabled en touchenabled, maar het kan één van de uitzonderingen zijn..
                    if (((UIElement)obj).IsEnabled)
                        return (Visual)obj;
                }
            }
            return null;
        }

        public Point RelativePosition
        {
            get
            {
                if (Selected.Element != null && Selected.Element is UIElement)
                {

                    return ((UIElement)Selected.Element).TranslatePoint(Finger.CurrentPosition, Selected.FrameworkElement); ;
                    //return Finger.Element.PointFromScreen(this.Finger.CurrentPosition);
                }
                return new Point();
            }
        }

        private Visual GetFirstTouchObject(Visual obj)
        {
            while (obj != null)
            {
                if (obj is Visual)
                {
                    if (obj is UIElement)
                    {
                        if ((bool)obj.GetValue(MTProperties.TouchEnabledProperty) && ((UIElement)obj).IsEnabled && (((UIElement)obj).Visibility == Visibility.Visible))
                        {
                            return obj;
                        }
                        else if (obj is Thumb || obj is RepeatButton || obj is ToggleButton)
                        {//Niet enabled en touchenabled, maar het kan één van de uitzonderingen zijn..
                            if (((UIElement)obj).IsEnabled && (((UIElement)obj).Visibility == Visibility.Visible))
                                return obj;
                        }
                    }
                    else if ((bool)obj.GetValue(MTProperties.TouchEnabledProperty))
                    {
                        return obj;
                    }
                    obj = (Visual)VisualTreeHelper.GetParent(obj);
                }
            }
            return obj;
        }
        private Visual GetFirstUserControl(Visual obj)
        {
            while (obj != null)
            {
                if (obj is UserControl)
                {
                    return obj;
                }
                obj = (Visual)VisualTreeHelper.GetParent(obj);
            }
            return obj;
        }

        public Touch()
        {
        }

        public Touch(List<DependencyObject> ht, FingerObject finger)
        {
            bool found = false;
            DependencyObject VisualHit = null;
                
            while (!found && ht != null && ht.Count > 0)
            {
                found = false;
                VisualHit = ht.First();

                
                if (!IsCollapsed((FrameworkElement)VisualHit))
                {
                    FrameworkElement obj = (FrameworkElement)VisualHit;
                    //if ((bool)obj.GetValue(MTProperties.TouchEnabledProperty) && ((UIElement)obj).IsEnabled && (((UIElement)obj).Visibility == Visibility.Visible))
                    {
                        found = true;
                    }
                }
                else
                {
                    ht.RemoveAt(0);
                }
            }

            if (VisualHit != null)
            {
                

                    this.Finger = finger;
                    if (VisualHit is Visual || VisualHit is DrawingVisual)
                    {
                        // selected element
                        Visual db = GetFirstTouchObject((Visual)VisualHit);

                        if (db != null)
                        {
                            this.Selected = new TouchedElement(db);
                            this.Stack = new TouchedElementStack();
                            if (this.Selected != null)
                            {

                                this.Finger.Element = this.Selected.Element;

                                Visual pobj = this.Selected.Element;
                                while (pobj != null)
                                {
                                    //het is een stack omdat er steeds parents toe worden gevoegd.. Dus het uiteindelijke
                                    //top element is degene die aangeraakt wordt.
                                    this.Stack.Add(new TouchedElement(pobj));
                                    //Console.WriteLine("added to stack:" + this.Stack.Last());
                                    Object o = (Object)VisualTreeHelper.GetParent(pobj);
                                    if (VisualTreeHelper.GetParent(pobj) != null && VisualTreeHelper.GetParent(pobj) is Visual)
                                    {

                                        pobj = GetFirstTouchObject((Visual)VisualTreeHelper.GetParent(pobj));
                                    }
                                    else
                                    {
                                        pobj = null;
                                    }
                                }
                            }
                        }

                    }
                    else if (VisualHit is Visual3D)// 3d
                    {
                        if (VisualHit is Viewport2DVisual3D)
                        {
                            Viewport2DVisual3D vp2dv3d = (Viewport2DVisual3D)VisualHit;
                            this.Selected = new TouchedElement(vp2dv3d.Visual);
                            this.Stack = new TouchedElementStack();
                            this.Finger.Element = this.Selected.Element;
                        }
                        else
                        {
                            // selected element
                            try
                            {

                                Visual db = (Visual)VisualTreeHelper.GetParent((Visual3D)VisualHit);


                                //RayMeshGeometry3DHitTestResult htr3D = (RayMeshGeometry3DHitTestResult)htr[0];
                                //GeometryModel3D geo = (GeometryModel3D)htr3D.ModelHit;
                                db = GetFirstTouchObject((Visual)db);
                                //db = GetFirstUserControl(db);

                                if (db != null)
                                {
                                    this.Selected = new TouchedElement(db);
                                    this.Stack = new TouchedElementStack();
                                    if (this.Selected != null)
                                    {
                                        this.Finger.Element = this.Selected.Element;
                                    }
                                }
                            }
                            catch (Exception e)
                            {

                            }
                        }
                
                }
                //temp = findTouchedUIElement((UIElement)obj);
                //Debug.WriteLine("TOUCHED ELEMENT: " + temp.GetType().ToString());
            }
            
        }

        private bool IsCollapsed(DependencyObject VisualHit)
        {
            DependencyObject fe = VisualHit;
            while (fe != null)
            {
                DependencyObject dob = VisualTreeHelper.GetParent(fe);
                if (dob != null)
                {
                    fe = dob;
                    if (fe is FrameworkElement)
                    {                        
                        if (((FrameworkElement)fe).Visibility == Visibility.Collapsed) return true;
                    }
                }
                else
                {
                    return false;
                }
            }            
            return false;
        }


    }
}
